package cn.xeblog.plugin.game.chess2;

import cn.xeblog.plugin.game.chess.ChessCache;
import cn.xeblog.plugin.game.chess2.chessmove.ChessMovePlay;
import cn.xeblog.plugin.game.chess2.chessmove.MoveNode;
import cn.xeblog.plugin.game.chess2.chessparam.ChessParam;
import cn.xeblog.plugin.game.chess2.enums.Alliance;
import cn.xeblog.plugin.game.chess2.enums.PieceType;
import cn.xeblog.plugin.game.chess2.evaluate.EvaluateComputeMiddleGame;
import cn.xeblog.plugin.game.chess2.zobrist.TranspositionTable;

import javax.swing.*;
import java.applet.Applet;
import java.applet.AudioClip;
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;

import static cn.xeblog.plugin.game.chess2.ChessConstant.*;

public class ChessBoardMain extends JPanel {

    private static final long serialVersionUID = 1L;

    /**
     * 行的数量
     */
    public static final int NUM_ROWS = 10;
    /**
     * 列的数量
     */
    public static final int NUM_COLS = 9;

    public static final String[] chessName = new String[]{"   ", null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, "黑将", "黑车", "黑车", "黑马", "黑马", "黑炮", "黑炮", "黑象", "黑象", "黑士", "黑士", "黑卒", "黑卒", "黑卒", "黑卒", "黑卒", "红将", "红车", "红车", "红马", "红马", "红炮", "红炮", "红象", "红象", "红士", "红士", "红卒", "红卒", "红卒", "红卒", "红卒",};
    public static final String[] chessIcon = new String[]{null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, "BK", "BR", "BR", "BN", "BN", "BC", "BC", "BB", "BB", "BA", "BA", "BP", "BP", "BP", "BP", "BP", "RK", "RR", "RR", "RN", "RN", "RC", "RC", "RB", "RB", "RA", "RA", "RP", "RP", "RP", "RP", "RP",};
    int lastTimeCheckedSite = -1; //上次选中棋子的位置
    private ButtonActionListener my = new ButtonActionListener();
    private List<PieceLabel> buttons = new ArrayList<PieceLabel>(BOARDSIZE90);
    int play = 1;
    /**
     * 0位黑方，1位红方
     */
    volatile boolean[] android = new boolean[]{false, false};
    int begin = -1;
    int end = 0;
    public ComputerLevel computerLevel = ComputerLevel.greenHand; //默认
    boolean isBackstageThink = false;
    boolean computeFig = false;
    TranspositionTable transTable;
    ChessMovePlay cmp = null;
    AICoreHandler _AIThink = new AICoreHandler();
    AICoreHandler backstageAIThink = new AICoreHandler();
    //	public static List<MoveNode> backMove=new ArrayList<MoveNode>();
    NodeLink moveHistory;
    int turn_num = 0;//回合数
    ChessParam chessParamCont;
    private static boolean isSound = false;

    JPanel jpanelContent;

    private int squareWidth;

    private JPoint[][] gBoard = new JPoint[NUM_ROWS][NUM_COLS];
    /**
     * 中国象棋设置页
     */
    private ChineseChess chineseChessPage;

    /**
     * 是否红方
     */
    private boolean isRed;


    public void initHandler() {
        String startFen;

        if (isRed) { // 红方
            startFen = "c6c5  rnbakabnr/9/1c5c1/p1p1p1p1p/9/9/P1P1P1P1P/1C5C1/9/RNBAKABNR b - - 0 1";
        } else { // 黑方
            startFen = "c6c5  RNBAKABNR/9/1C5C1/P1P1P1P1P/9/9/p1p1p1p1p/1c5c1/9/rnbakabnr b - - 0 1";
        }


//		String startFen="c6c5  9/CP2k4/9/9/9/9/9/9/9/4K4 b - - 0 1";
//		Tools.parseFENtoBoardZobrist(fenStr);
//        startFen = readSaved();

        String[] fenArray = Tools.fenToFENArray(startFen);
        int[] boardTemp = Tools.parseFEN(fenArray[1]);
        //根据棋盘初始参数
        chessParamCont = ChessInitialize.getGlobalChessParam(boardTemp);
        //清除所有界面图片
//		clearBoardIcon();
        //初始界面棋子
        for (int i = 0; i < boardTemp.length; i++) {
            if (boardTemp[i] > 0) {
                this.setBoardIconUnchecked(i, boardTemp[i]);
            }
        }

        //初始局面(要把棋子摆好后才能计算局面值)
        transTable = new TranspositionTable();
        if (moveHistory == null) {
            moveHistory = new NodeLink(1 - play, transTable.boardZobrist32, transTable.boardZobrist64);
        }
//        play = 1 - moveHistory.play;
//        android[1 - play] = true;
        cmp = new ChessMovePlay(chessParamCont, transTable, new EvaluateComputeMiddleGame(chessParamCont));
    }


    private void setCenter() {
        if (jpanelContent != null) {
            this.remove(jpanelContent);
        }

        jpanelContent = new BoardPane();


//        jpanelContent = new JPanel() {
//
//            private JPoint[][] gBoard = new JPoint[10][9];
//
//            @Override
//            protected void paintComponent(Graphics g) {
//                super.paintComponent(g);
//
//                for (int row = 0; row < 10; row++) {
//                    for (int col = 0; col < 9; col++) {
//                        gBoard[row][col] = new JPoint(row, col); //wei
//                    }
//                }
//
//                squareWidth = 32;
//                int radius = squareWidth * 4 / 10;
//                int xDisplacement, yDisplacement;
//                for (int y = 0; y < 10; y++) {
//                    for (int x = 0; x < 9; x++) {
//                        xDisplacement = (4 - x) * squareWidth;
//                        yDisplacement = (10 - 2 * y) * squareWidth / 2 - squareWidth / 3;
//                        gBoard[y][x].setPosition(getWidth() / 2 - xDisplacement, 8 + getHeight() / 2 - yDisplacement);
//                    }
//                }
//
//                Graphics2D g2 = (Graphics2D) g;
//                drawBoard(g2);
//            }
//
//            private void drawBoard(Graphics2D g2) {
//                g2.setColor(Color.black);
////        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
//
//                for (int y = 0; y < 10; y++) {
//                    for (int x = 0; x < 9; x++) {
//                        if (x == 8) continue;
////                    g2.drawLine(board.getPoint(x, y).getX(), board.getPoint(x, y).getY(), board.getPoint(x + 1, y).getX(), board.getPoint(x + 1, y).getY());
//                        g2.drawLine(gBoard[y][x].getX(), gBoard[y][x].getY(), gBoard[y][x + 1].getX(), gBoard[y][x + 1].getY());
//                    }
//                    for (int x = 0; x < 9; x++) {
//                        if (y == 9) continue;
//                        else if (y == 4 && x < 8 && x > 0) continue;
////                    g2.drawLine(board.getPoint(x, y).getX(), board.getPoint(x, y).getY(), board.getPoint(x, y + 1).getX(), board.getPoint(x, y + 1).getY());
//                        g2.drawLine(gBoard[y][x].getX(), gBoard[y][x].getY(), gBoard[y + 1][x].getX(), gBoard[y + 1][x].getY());
//                    }
//                }
//                //draws the middle square
//                g2.drawLine(gBoard[0][3].getX(), gBoard[0][3].getY(), gBoard[2][5].getX(), gBoard[2][5].getY());
//                g2.drawLine(gBoard[0][5].getX(), gBoard[0][5].getY(), gBoard[2][3].getX(), gBoard[2][3].getY());
//                g2.drawLine(gBoard[7][3].getX(), gBoard[7][3].getY(), gBoard[9][5].getX(), gBoard[9][5].getY());
//                g2.drawLine(gBoard[7][5].getX(), gBoard[7][5].getY(), gBoard[9][3].getX(), gBoard[9][3].getY());
//
//
//                //marks up the top half of the board
//                drawPoint(g2, gBoard[2][1], 0, 360);
//                drawPoint(g2, gBoard[2][7], 0, 360);
//                drawPoint(g2, gBoard[3][0], -90, 90);
//                drawPoint(g2, gBoard[3][2], 0, 360);
//                drawPoint(g2, gBoard[3][4], 0, 360);
//                drawPoint(g2, gBoard[3][6], 0, 360);
//                drawPoint(g2, gBoard[3][8], 90, 270);
//
//                //marks up the bottom half of the board
//                drawPoint(g2, gBoard[6][0], -90, 90);
//                drawPoint(g2, gBoard[6][2], 0, 360);
//                drawPoint(g2, gBoard[6][4], 0, 360);
//                drawPoint(g2, gBoard[6][6], 0, 360);
//                drawPoint(g2, gBoard[6][8], 90, 270);
//                drawPoint(g2, gBoard[7][1], 0, 360);
//                drawPoint(g2, gBoard[7][7], 0, 360);
//            }
//
//            private void drawPoint(Graphics2D g2, JPoint point, int startAngle, int endAngle) {
//                int n = 0;
//                int m = 0;
//                for (int x = startAngle / 90; x < endAngle / 90; x++) {
//                    g2.drawLine(point.getX() + (int) (Math.cos(Math.toRadians(45 + 90 * x)) * squareWidth / 10) + n, point.getY() + (int) (Math.sin(Math.toRadians(45 + 90 * x)) * squareWidth / 10), point.getX() + (int) (Math.cos(Math.toRadians(45 + 90 * x)) * squareWidth / 10), point.getY() + (int) (Math.sin(Math.toRadians(45 + 90 * x)) * squareWidth / 5));
//                    g2.drawLine(point.getX() + (int) (Math.cos(Math.toRadians(45 + 90 * x)) * squareWidth / 10) + n, point.getY() + (int) (Math.sin(Math.toRadians(45 + 90 * x)) * squareWidth / 10) + m, point.getX() + (int) (Math.cos(Math.toRadians(45 + 90 * x)) * squareWidth / 5) + n, point.getY() + (int) (Math.sin(Math.toRadians(45 + 90 * x)) * squareWidth / 10) + m);
//                }
//            }
//        };
//        jpanelContent. setMinimumSize(new Dimension(230, 250));
//        jpanelContent.setMaximumSize(new Dimension(230, 250));
//        jpanelContent.setSize(new Dimension(230, 250));
//        jpanelContent.setOpaque(false);
        jpanelContent.setBorder(BorderFactory.createLineBorder(Color.red));

        this.setLayout(new BorderLayout());


//        jpanelContent.setLayout(new BorderLayout());
        //北
//        JPanel jpNorth = new JPanel();
//        jpNorth.setPreferredSize(new Dimension(25, 25));
////		jpNorth.setBackground(Color.white);
//        jpNorth.setOpaque(false);
//        jpanelContent.add(jpNorth, BorderLayout.NORTH);
//        //南
//        JPanel jpSouth = new JPanel();
//        jpSouth.setPreferredSize(new Dimension(5, 5));
//        jpSouth.setBackground(Color.black);
//        jpSouth.setOpaque(false);
//        jpanelContent.add(jpSouth, BorderLayout.SOUTH);
//        //西
//        JPanel jpWest = new JPanel();
//        jpWest.setPreferredSize(new Dimension(20, 20));
//        jpWest.setBackground(Color.blue);
//        jpWest.setOpaque(false);
//        jpanelContent.add(jpWest, BorderLayout.WEST);
//        //东
//        JPanel jpEast = new JPanel();
//        jpEast.setPreferredSize(new Dimension(20, 20));
//        jpEast.setBackground(Color.CYAN);
//        jpEast.setOpaque(false);
//        jpanelContent.add(jpEast, BorderLayout.EAST);
        //中
//        JPanel panel = new JPanel();
//        panel.setLayout(new GridLayout(10, 9));
//        panel.setPreferredSize(new Dimension(100, 100));
//        panel.setOpaque(false);
//        panel.setBorder(BorderFactory.createLineBorder(Color.red));
//        jpanelContent.add(panel, BorderLayout.CENTER);

//        for (int i = 0; i < BOARDSIZE90; i++) {
//            JLabel p = new JLabel();
//            p.setBorder(BorderFactory.createLineBorder(Color.blue));
//            p.addMouseListener(my);
//            p.setBackground(Color.red);
//            p.setSize(32, 24);
//            buttons[i] = p;
//            panel.add(p);
//        }
//        int i = 0;
//        for (int y = 0; y < 10; y++) {
//            for (int x = 0; x < 9; x++) {
//                JLabel p = new JLabel();
//                p.setBorder(BorderFactory.createLineBorder(Color.blue));
//                p.addMouseListener(my);
//                p.setBackground(Color.red);
//                p.setSize(32, 24);
//                buttons[i++] = p;
//                panel.add(p);
//            }
//        }
        this.add(jpanelContent, BorderLayout.CENTER);
    }

    public ChessBoardMain(ChineseChess chineseChess) {
//        super("中国象棋");
        this.chineseChessPage = chineseChess;

        setCenter();

        JPanel constrol = new JPanel();
        constrol.setLayout(new GridLayout(1, 3));


        Button button = new Button("悔棋");
        button.addActionListener(my);
        Button computerMove = new Button("立即走棋");
        computerMove.addActionListener(my);
        constrol.add(button);
        constrol.add(computerMove);
        this.add(constrol, BorderLayout.SOUTH);

        JPanel menuPane = new JPanel();
        Box vBox = Box.createVerticalBox();
        vBox.add(Box.createVerticalStrut(10));

        Box red = Box.createHorizontalBox();
        red.add(chineseChessPage.getPrePageButton());
        red.add(Box.createHorizontalStrut(210));
        vBox.add(red);

        menuPane.add(vBox);
        this.add(menuPane, BorderLayout.NORTH);

//        this.addWindowListener(my);
        if (null == chineseChessPage.chessCache || !ChessCache.Mode.ONLINE.equals(chineseChessPage.chessCache.currentMode)) {
            //初始处理器
            initHandler();
        }
//        this.setJMenuBar(setJMenuBar());

        this.setSize(568, 680);
//        this.setLocationRelativeTo(null);
//        this.setResizable(false);
        this.setVisible(true);

    }

    private MenuItemActionListener menuItemAction = new MenuItemActionListener();
    JRadioButtonMenuItem hashSize2M = new JRadioButtonMenuItem("HASH表小", true);
    JRadioButtonMenuItem hashSize32M = new JRadioButtonMenuItem("HASH表中", false);
    JRadioButtonMenuItem hashSize64M = new JRadioButtonMenuItem("HASH表大", false);

    private JMenuBar setJMenuBar() {
        JMenuBar jmb = new JMenuBar();
        JMenu menu_file = new JMenu("文件");
        JMenuItem create = new JMenuItem("新建");
        JMenuItem save = new JMenuItem("保存");
        JRadioButtonMenuItem mi_6 = new JRadioButtonMenuItem("菜鸟", true);
        JRadioButtonMenuItem mi_7 = new JRadioButtonMenuItem("入门", false);
        JRadioButtonMenuItem mi_8 = new JRadioButtonMenuItem("业余", false);
        JRadioButtonMenuItem mi_9 = new JRadioButtonMenuItem("专家", false);
        JRadioButtonMenuItem mi_10 = new JRadioButtonMenuItem("大师", false);
        JRadioButtonMenuItem mi_11 = new JRadioButtonMenuItem("无敌", false);

        ButtonGroup group = new ButtonGroup();
        group.add(mi_6);
        group.add(mi_7);
        group.add(mi_8);
        group.add(mi_9);
        group.add(mi_10);
        group.add(mi_11);
        create.addActionListener(menuItemAction);
        save.addActionListener(menuItemAction);
        mi_6.addActionListener(menuItemAction);
        mi_7.addActionListener(menuItemAction);
        mi_8.addActionListener(menuItemAction);
        mi_9.addActionListener(menuItemAction);
        mi_10.addActionListener(menuItemAction);
        mi_11.addActionListener(menuItemAction);

        create.setMnemonic(10);
        mi_6.setMnemonic(2);
        mi_7.setMnemonic(3);
        mi_8.setMnemonic(4);
        mi_9.setMnemonic(5);
        mi_10.setMnemonic(6);
        menu_file.setMnemonic('0');
        menu_file.add(create);
        menu_file.add(mi_6);
        menu_file.add(mi_7);
        menu_file.add(mi_8);
        menu_file.add(mi_9);
        menu_file.add(mi_10);
        menu_file.add(mi_11);
        menu_file.add(save);
        jmb.add(menu_file);
        //------------------------------------------------------
        JMenu menu_set = new JMenu("设置");
        JCheckBoxMenuItem redCmp = new JCheckBoxMenuItem("电脑红方", play != REDPLAYSIGN);
        JCheckBoxMenuItem blackCmp = new JCheckBoxMenuItem("电脑黑方", play != BLACKPLAYSIGN);

        JCheckBoxMenuItem isSoundBox = new JCheckBoxMenuItem("音效", isSound);


        ButtonGroup hashSizeGroup = new ButtonGroup();
        hashSizeGroup.add(hashSize2M);
        hashSizeGroup.add(hashSize32M);
        hashSizeGroup.add(hashSize64M);


        JCheckBoxMenuItem backstageThink = new JCheckBoxMenuItem("后台思考", isBackstageThink);

        redCmp.addActionListener(menuItemAction);
        blackCmp.addActionListener(menuItemAction);
        hashSize2M.addActionListener(menuItemAction);
        hashSize32M.addActionListener(menuItemAction);
        hashSize64M.addActionListener(menuItemAction);
        backstageThink.addActionListener(menuItemAction);
        isSoundBox.addActionListener(menuItemAction);

        menu_set.add(blackCmp);
        menu_set.add(redCmp);
        menu_set.add(hashSize2M);
        menu_set.add(hashSize32M);
        menu_set.add(hashSize64M);
        menu_set.add(backstageThink);
        menu_set.add(isSoundBox);
        jmb.add(menu_set);
        return jmb;
    }

    public void setBoardIconUnchecked(int site, int chess) {
        if (chess == NOTHING) {
            buttons.get(site).setPieceType(PieceType.OTHER);
        } else {
            PieceType match = PieceType.match(chessIcon[chess]);
            buttons.get(site).setPieceType(match);
        }
        buttons.get(site).setSelected(false);
        buttons.get(site).updateUI();
    }

    public void setBoardIconChecked(int site, int chess) {
//        buttons[site].setIcon(getImageIcon(chessIcon[chess] + "S"));
        if (chess == NOTHING) {
            buttons.get(site).setPieceType(PieceType.OTHER);
        } else {
            PieceType match = PieceType.match(chessIcon[chess]);
            buttons.get(site).setPieceType(match);
        }
        buttons.get(site).setSelected(true);
        buttons.get(site).updateUI();
    }

    public void setCheckedLOSS(int play) {
        buttons.get(chessParamCont.allChess[chessPlay[play]]).setIcon(getImageIcon(chessIcon[chessPlay[play]] + "M"));
    }

    public void clearBoardIcon() {
        for (int i = 0; i < buttons.size(); i++) {
            buttons.get(i).setIcon(null);
        }
    }

    public void initBoardRelation(int destSite, int chess) {

        chessParamCont.board[destSite] = chess;
        chessParamCont.allChess[chess] = destSite;

        int destRow = boardRow[destSite];
        int destCol = boardCol[destSite];
        chessParamCont.boardBitRow[destRow] |= (1 << (8 - destCol));
        chessParamCont.boardBitCol[destCol] |= (1 << (9 - destRow));

    }

    public void move(MoveNode moveNode) {

        if (lastTimeCheckedSite != -1) {
            setBoardIconUnchecked(lastTimeCheckedSite, chessParamCont.board[lastTimeCheckedSite]);
        }
        setBoardIconUnchecked(moveNode.srcSite, NOTHING);
        setBoardIconChecked(moveNode.destSite, moveNode.srcChess);
        lastTimeCheckedSite = moveNode.destSite;
    }

    class ButtonActionListener implements ActionListener, WindowListener, MouseListener {
        public void actionPerformed(ActionEvent e) {
            Button sour = (Button) e.getSource();
            if (sour.getLabel().equals("悔棋")) {
                if (moveHistory.getMoveNode() != null) {
                    MoveNode moveNode = moveHistory.getMoveNode();
                    unMoveNode(moveNode);
                    moveHistory = moveHistory.getLastLink();
                    turn_num--;
                    play = 1 - play; //交换双方
                }
            } else if (sour.getLabel().equals("立即走棋")) {
                if (_AIThink != null) {
                    _AIThink.setStop();
                }
            }


        }

        private boolean checkZFPath(int srcSite, int destSite, int play) {
            if (chessParamCont.board[srcSite] == NOTHING) {
                return false;
            }
//			int row=chessParamCont.boardBitRow[boardRow[srcSite]];
//			int col=chessParamCont.boardBitCol[boardCol[srcSite]];
			/*BitBoard bt = BitBoard.assignXorToNew(GunBitBoardOfFakeAttackRow[srcSite][row],GunBitBoardOfFakeAttackCol[srcSite][col]);
			System.out.println(chessParamCont.maskBoardChesses);
			System.out.println("============炮伪攻击的位置==========");
			System.out.println(bt);*/
//			System.out.println("车或炮的机动性为->>"+(ChariotAndGunMobilityRow[srcSite][row]+ChariotAndGunMobilityCol[srcSite][col]));

            MoveNode moveNode = new MoveNode(srcSite, destSite, chessParamCont.board[srcSite], chessParamCont.board[destSite], 0);
            return cmp.legalMove(play, moveNode);
        }

        private void unMoveNode(MoveNode moveNode) {
            MoveNode unmoveNode = new MoveNode();
            unmoveNode.srcChess = moveNode.destChess;
            unmoveNode.srcSite = moveNode.destSite;
            unmoveNode.destChess = moveNode.srcChess;
            unmoveNode.destSite = moveNode.srcSite;
            unMove(unmoveNode);
            cmp.unMoveOperate(moveNode);
        }

        private void unMove(MoveNode moveNode) {
            if (lastTimeCheckedSite != -1) {
                setBoardIconUnchecked(lastTimeCheckedSite, chessParamCont.board[lastTimeCheckedSite]);
            }
            if (moveNode.srcChess == NOTHING) {
                buttons.get(moveNode.srcSite).setIcon(null);
            } else {
                setBoardIconUnchecked(moveNode.srcSite, moveNode.srcChess);
            }
            if (moveNode.destChess == NOTHING) {
                buttons.get(moveNode.destChess).setIcon(null);
            } else {
                setBoardIconChecked(moveNode.destSite, moveNode.destChess);
            }
            lastTimeCheckedSite = moveNode.destSite;
        }

        public void windowActivated(WindowEvent arg0) {
            // TODO Auto-generated method stub

        }

        public void windowClosed(WindowEvent arg0) {
            // TODO Auto-generated method stub

        }

        public void windowClosing(WindowEvent arg0) {
            // TODO Auto-generated method stub
            System.exit(1);
        }

        public void windowDeactivated(WindowEvent arg0) {
            // TODO Auto-generated method stub

        }

        public void windowDeiconified(WindowEvent arg0) {
            // TODO Auto-generated method stub

        }

        public void windowIconified(WindowEvent arg0) {
            // TODO Auto-generated method stub

        }

        public void windowOpened(WindowEvent arg0) {
            // TODO Auto-generated method stub

        }


        public void mouseClicked(MouseEvent e) {
            // TODO Auto-generated method stub

        }

        public void mouseEntered(MouseEvent e) {
            // TODO Auto-generated method stub

        }

        public void mouseExited(MouseEvent e) {
            // TODO Auto-generated method stub

        }

        public void mousePressed(MouseEvent e) {
            if (android[play]) {
                return;
            }
            for (int i = 0; i < buttons.size(); i++) {
                PieceLabel p = buttons.get(i);
                if (p == e.getSource()) {
                    if (chessParamCont.board[i] != NOTHING && (chessParamCont.board[i] & chessPlay[play]) == chessPlay[play]) {//自方子力
                        if (i != begin) {
                            begin = i;

                            setBoardIconChecked(i, chessParamCont.board[i]);
                            if (lastTimeCheckedSite != -1) {
                                setBoardIconUnchecked(lastTimeCheckedSite, chessParamCont.board[lastTimeCheckedSite]);
                            }
                            lastTimeCheckedSite = begin;
                        }
                        return;
                    } else if (begin == -1) {
                        return;
                    }
                    end = i;
                    if (this.checkZFPath(begin, end, play)) {
                        MoveNode moveNode = new MoveNode(begin, end, chessParamCont.board[begin], chessParamCont.board[end], 0);
                        showMoveNode(moveNode);
                        NodeLink nextLink = new NodeLink(play, transTable.boardZobrist32, transTable.boardZobrist64);
                        nextLink.setMoveNode(moveNode);
                        moveHistory.setNextLink(nextLink);
                        moveHistory = moveHistory.getNextLink();
                        begin = -1;
                        opponentMove();
                    }
                }
            }

        }

        public void mouseReleased(MouseEvent e) {
            // TODO Auto-generated method stub

        }
    }

    public void gameOverMsg(String msg) {
        if (JOptionPane.showConfirmDialog(this, msg + "是否继续？", "信息", JOptionPane.YES_NO_OPTION) == JOptionPane.YES_OPTION) {
//            dispose();
            new ChessBoardMain(chineseChessPage);
        } else {
//            dispose();
        }
    }

    private ImageIcon getImageIcon(String chessName) {
        String path = "/games/images/" + chessName + ".GIF";
        ImageIcon imageIcon = new ImageIcon(getClass().getResource(path));
        ImageIcon icon = new ImageIcon(imageIcon.getImage().getScaledInstance(32, 32, Image.SCALE_SMOOTH));
        return icon;
    }

    private boolean checkGameOver() {
        boolean isGameOver = false;
        String msg = null;
        if (moveHistory == null || moveHistory.getMoveNode() == null) {
            msg = (play == BLACKPLAYSIGN ? "黑方" : "红方") + "被残忍的将死！";
            isGameOver = true;
            //自己帅被吃
        } else if (chessParamCont.allChess[chessPlay[BLACKPLAYSIGN]] == NOTHING || moveHistory.getMoveNode().destChess == chessPlay[BLACKPLAYSIGN]) {
            isGameOver = true;
            msg = "黑方被完虐！";
        } else if (chessParamCont.allChess[chessPlay[REDPLAYSIGN]] == NOTHING || moveHistory.getMoveNode().destChess == chessPlay[REDPLAYSIGN]) {
            msg = "红方被完虐！";
            isGameOver = true;
        } else if (moveHistory.getMoveNode().score == -LONGCHECKSCORE) {
            msg = (play == BLACKPLAYSIGN ? "黑方" : "红方") + "长将判负！";
            isGameOver = true;
        } else if (moveHistory.getMoveNode().score <= -(maxScore - 2)) {
            setCheckedLOSS(play);
            msg = (play == BLACKPLAYSIGN ? "黑方" : "红方") + "被残忍的将死！";
            isGameOver = true;
        } else if (moveHistory.getMoveNode().score >= (maxScore - 2)) {
            setCheckedLOSS(1 - play);
            msg = (play == BLACKPLAYSIGN ? "黑方" : "红方") + "赢得了最终的胜利！";
            isGameOver = true;
        } else if (chessParamCont.getAttackChessesNum(REDPLAYSIGN) == 0 && chessParamCont.getAttackChessesNum(BLACKPLAYSIGN) == 0) {
            msg = "双方都无攻击棋子此乃和棋！";
            isGameOver = true;
        } else if (turn_num >= 300) {
            msg = "大战300回合未分胜负啊！";
            isGameOver = true;
        }
        if (isGameOver) {
            launchSound(SoundEffect.LOSS_SOUND);
            gameOverMsg(msg);
        } else {
            MoveNode moveNode = moveHistory.getMoveNode();
            if (cmp.checked(1 - play)) {//对手是否被将
                launchSound(SoundEffect.CHECKED_SOUND);
            } else if (moveNode.destChess != NOTHING) {
                launchSound(SoundEffect.CAPTURE_SOUND);
            } else {
                launchSound(SoundEffect.MOVE_SOUND);
            }
        }
        return isGameOver;
    }

    class MenuItemActionListener implements ActionListener {
        public void actionPerformed(ActionEvent e) {
            String actionCommand = e.getActionCommand();
            if ("新建".equals(actionCommand)) {
//                dispose();
                new ChessBoardMain(chineseChessPage);
            } else if ("保存".equalsIgnoreCase(actionCommand)) {
                Tools.saveFEN(chessParamCont.board, moveHistory);
            } else if ("菜鸟".equals(actionCommand)) {
                computerLevel = ComputerLevel.greenHand;
            } else if ("入门".equals(actionCommand)) {
                computerLevel = ComputerLevel.introduction;
            } else if ("业余".equals(actionCommand)) {
                computerLevel = ComputerLevel.amateur;
            } else if ("专家".equals(actionCommand)) {
                computerLevel = ComputerLevel.career;
            } else if ("大师".equals(actionCommand)) {
                computerLevel = ComputerLevel.master;
            } else if ("无敌".equals(actionCommand)) {
                computerLevel = ComputerLevel.invincible;
            } else if ("电脑红方".equals(actionCommand)) {
                android[REDPLAYSIGN] = !android[REDPLAYSIGN];
                if (android[REDPLAYSIGN] && (REDPLAYSIGN == play || turn_num <= 0)) {
                    if (turn_num <= 0) {
                        play = REDPLAYSIGN;
                        moveHistory.play = 1 - REDPLAYSIGN;
                    }
                    computeThinkStart();
                }
            } else if ("电脑黑方".equals(actionCommand)) {
                android[BLACKPLAYSIGN] = !android[BLACKPLAYSIGN];
                if (android[BLACKPLAYSIGN] && (BLACKPLAYSIGN == play || turn_num <= 0)) {
                    if (turn_num <= 0) {
                        play = BLACKPLAYSIGN;
                        moveHistory.play = 1 - BLACKPLAYSIGN;
                    }
                    computeThinkStart();
                }
            } else if ("HASH表小".equals(actionCommand)) {
                if (turn_num == 0) {
                    TranspositionTable.setHashSize(0x7FFFF);
                }
            } else if ("HASH表中".equals(actionCommand)) {
                if (turn_num == 0) {
                    TranspositionTable.setHashSize(0xFFFFF);
                }
            } else if ("HASH表大".equals(actionCommand)) {
                if (turn_num == 0) {
                    TranspositionTable.setHashSize(0x1FFFFF);
                }
            } else if ("后台思考".equals(actionCommand)) {
                isBackstageThink = !isBackstageThink;
            } else if ("音效".equals(actionCommand)) {
                isSound = !isSound;
            }
        }

    }

    private void opponentMove() {
        setHashTablesEnabled();
        //查看是否以胜利
        if (!checkGameOver()) {
            turn_num++;
            play = 1 - play; //交换双方
            //对手是否为电脑
            if (android[play]) {
                computeThinkStart();
            }
        }
    }

    private void computeThinkStart() {
        //设置后台思考
        if (isBackstageThink && (guessLink != null && moveHistory != null)) {
            //查看是否猜中
            if (guessLink.getMoveNode().equals(moveHistory.getMoveNode())) {
                new Thread() {
                    public void run() {
                        System.out.println("---->猜测命中！！");
                        try {
                            //加入时间控制
                            backstageAIThink.launchTimer();
                            backstageThinkThread.join();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                            computeThink();
                        }
                        computeAIMoving(guessLink.getNextLink());
                    }
                }.start();
            } else {
                new Thread() {
                    public void run() {
                        System.out.println("--->未命中");
                        //如果没中进行运算
                        backstageAIThink.setStop();
                        try {
                            backstageThinkThread.join();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        System.out.println("--->重新思考");
                        computeThink();
                    }
                }.start();
            }
        } else {
            computeThink();
        }
    }

    private void computeThink() {
        new Thread() {
            public void run() {
                _AIThink.setLocalVariable(computerLevel, chessParamCont, moveHistory);
                _AIThink.launchTimer();
                _AIThink.run();
                computeAIMoving(moveHistory.getNextLink());
            }
        }.start();
    }

    private void computeAIMoving(NodeLink nodeLink) {
        moveHistory = nodeLink;
        // if(!checkGameOver()){
        if (nodeLink != null && nodeLink.getMoveNode() != null) {
            MoveNode moveNode = nodeLink.getMoveNode();
            showMoveNode(moveNode);
        }
        opponentMove();
        backstageThink();
        // }
    }

    private Thread backstageThinkThread = null;
    private NodeLink guessLink;

    //后台思考
    private void backstageThink() {
        if (!isBackstageThink) {
            return;
        }
        if (moveHistory.getNextLink() != null && moveHistory.getNextLink().getMoveNode() != null) {

            backstageThinkThread = new Thread() {
                public void run() {
                    //猜测的着法
                    guessLink = moveHistory.getNextLink();
                    backstageAIThink.setLocalVariable(computerLevel, chessParamCont, guessLink);
                    System.out.println("---->开始猜测(" + guessLink.getMoveNode() + ")");
                    backstageAIThink.guessRun(guessLink.getMoveNode());
                }
            };
            backstageThinkThread.start();
        }
    }

    private void showMoveNode(MoveNode moveNode) {
        if (moveNode != null) {
            move(moveNode);
            cmp.moveOperate(moveNode);
            transTable.synchroZobristBoardToStatic();
        }
    }

    private void setHashTablesEnabled() {
        hashSize2M.setEnabled(false);
        hashSize32M.setEnabled(false);
        hashSize64M.setEnabled(false);
    }

    /*
     * 记取上次保存记录
     */
    public String readSaved() {
        String fen = null;
        FileInputStream fileInput = null;
        try {
            File chessFile = new File("chess.txt");
            fileInput = new FileInputStream(chessFile);
            BufferedReader bufferedReader = new BufferedReader(new java.io.InputStreamReader(fileInput));

            while (bufferedReader.ready()) {
                fen = bufferedReader.readLine();
            }
            if (fen != null) {
                if (JOptionPane.showConfirmDialog(this, "检测到有存档是否继续上次游戏?", "信息", JOptionPane.YES_NO_OPTION) == JOptionPane.YES_OPTION) {
                    ObjectInputStream objInput = null;
                    try {
                        objInput = new ObjectInputStream(new FileInputStream("moves.dat"));
                        moveHistory = (NodeLink) objInput.readObject();
                        turn_num = 20;
                    } catch (Exception e) {
                        System.err.println("========读取历史记录出错 moves.dat");
                    } finally {
                        if (objInput != null) {
                            objInput.close();
                        }
                    }
                } else {
                    chessFile.deleteOnExit();
                    fen = "c6c5  rnbakabnr/9/1c5c1/p1p1p1p1p/9/9/P1P1P1P1P/1C5C1/9/RNBAKABNR b - - 0 1";
                }
            }
        } catch (Exception e) {
            fen = "c6c5  rnbakabnr/9/1c5c1/p1p1p1p1p/9/9/P1P1P1P1P/1C5C1/9/RNBAKABNR b - - 0 1";
        } finally {
            if (fileInput != null) {
                try {
                    fileInput.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return fen;
    }

//    public static void main(String args[]) {
//        new ChessBoardMain();
//    }

    public void launchSound(int type) {
        if (isSound) { //开启音效
            new SoundEffect(type).start();
        }
    }

    private static final String movePathPath = "/sounds/MOVE.WAV";
    private static final String checkedPath = "/sounds/CHECKED.WAV";
    private static final String capturePath = "/sounds/CAPTURE.WAV";
    private static final String lossPath = "/sounds/LOSS.WAV";
    private static final URL MOVEPATHURL = ChessBoardMain.class.getResource(movePathPath);
    private static final URL CHECKEDURL = ChessBoardMain.class.getResource(checkedPath);
    private static final URL CAPTUREURL = ChessBoardMain.class.getResource(capturePath);
    private static final URL LOSSURL = ChessBoardMain.class.getResource(lossPath);

    class SoundEffect extends Thread {
        public final static int MOVE_SOUND = 1;
        public final static int CAPTURE_SOUND = 2;
        public final static int CHECKED_SOUND = 3;
        public final static int LOSS_SOUND = 4;

        URL url = null;

        public SoundEffect(int k) {
            this.setDaemon(true);
            switch (k) {
                case MOVE_SOUND:
                    url = MOVEPATHURL;
                    break;
                case CAPTURE_SOUND:
                    url = CAPTUREURL;
                    break;
                case CHECKED_SOUND:
                    url = CHECKEDURL;
                    break;
                case LOSS_SOUND:
                    url = LOSSURL;
                    break;
            }
        }

        public void run() {
            AudioClip clip = Applet.newAudioClip(url);
            clip.play();
        }
    }

    class BoardPane extends JPanel {

        /**
         * 棋盘点位
         */
        private JPoint[][] gBoard = new JPoint[NUM_ROWS][NUM_COLS];

        /**
         * 棋子Label
         */
        private PieceLabel[][] pointIcons = new PieceLabel[NUM_ROWS][NUM_COLS];

        private int squareWidth;

        public BoardPane() {
            super();
            setLayout(new GridLayout(NUM_ROWS, NUM_COLS));
            this.setMinimumSize(new Dimension(230, 250));
            this.setMaximumSize(new Dimension(230, 250));
            this.setSize(new Dimension(230, 250));
            this.setOpaque(false);
            this.setBorder(BorderFactory.createLineBorder(Color.red));

            // 棋盘
            for (int row = 0; row < NUM_ROWS; row++) {
                for (int col = 0; col < NUM_COLS; col++) {
                    gBoard[row][col] = new JPoint(row, col); //wei
                }
            }

            // 棋子
            int i = 0;
            for (int y = 0; y < NUM_ROWS; y++) {
                for (int x = 0; x < NUM_COLS; x++) {
                    pointIcons[y][x] = new PieceLabel(x, y, gBoard[y][x]);
//                    pointIcons[y][x].setBorder(BorderFactory.createLineBorder(Color.blue));

                    pointIcons[y][x].addMouseListener(my);
                    pointIcons[y][x].setBackground(Color.red);
//                    p.setSize(32, 32);
                    buttons.add(i++, pointIcons[y][x]);


                    //pointIcons[y][x] = new JLabel();
                    //pointIcons[y][x].addMouseListener(handler);
                    //pointIcons[x][y].setBackground(Color.black);
                    //pointIcons[x][y].setOpaque(true);
                    add(pointIcons[y][x]);
                }
            }
        }

        //    @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);

            squareWidth = 32;

            int radius = squareWidth * 4 / 8;
            int xDisplacement, yDisplacement;
            for (int y = 0; y < NUM_ROWS; y++) {
                for (int x = 0; x < NUM_COLS; x++) {
                    xDisplacement = (4 - x) * squareWidth;
                    yDisplacement = (10 - 2 * y) * squareWidth / 2 - squareWidth / 3;
                    gBoard[y][x].setPosition(getWidth() / 2 - xDisplacement, 8 + getHeight() / 2 - yDisplacement);
                    pointIcons[y][x].setLocation(gBoard[y][x].getX() - radius, gBoard[y][x].getY() - radius);
                    pointIcons[y][x].setSize(radius * 2, radius * 2);
                }
            }

            Graphics2D g2 = (Graphics2D) g;
            drawBoard(g2);
        }

        private void drawBoard(Graphics2D g2) {
            g2.setColor(Color.black);
//        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

            // 横
            for (int y = 0; y < NUM_ROWS; y++) {
                for (int x = 0; x < NUM_COLS; x++) {
                    if (x == 8) continue;
                    g2.drawLine(gBoard[y][x].getX(), gBoard[y][x].getY(), gBoard[y][x + 1].getX(), gBoard[y][x + 1].getY());
                }
                // 竖线
                for (int x = 0; x < NUM_COLS; x++) {
                    if (y == 9) continue;
                    else if (y == 4 && x < 8 && x > 0) continue;
                    g2.drawLine(gBoard[y][x].getX(), gBoard[y][x].getY(), gBoard[y + 1][x].getX(), gBoard[y + 1][x].getY());
                }
            }
            //draws the middle square
            g2.drawLine(gBoard[0][3].getX(), gBoard[0][3].getY(), gBoard[2][5].getX(), gBoard[2][5].getY());
            g2.drawLine(gBoard[0][5].getX(), gBoard[0][5].getY(), gBoard[2][3].getX(), gBoard[2][3].getY());
            g2.drawLine(gBoard[7][3].getX(), gBoard[7][3].getY(), gBoard[9][5].getX(), gBoard[9][5].getY());
            g2.drawLine(gBoard[7][5].getX(), gBoard[7][5].getY(), gBoard[9][3].getX(), gBoard[9][3].getY());


            //marks up the top half of the board
            drawPoint(g2, gBoard[2][1], 0, 360);
            drawPoint(g2, gBoard[2][7], 0, 360);
            drawPoint(g2, gBoard[3][0], -90, 90);
            drawPoint(g2, gBoard[3][2], 0, 360);
            drawPoint(g2, gBoard[3][4], 0, 360);
            drawPoint(g2, gBoard[3][6], 0, 360);
            drawPoint(g2, gBoard[3][8], 90, 270);

            //marks up the bottom half of the board
            drawPoint(g2, gBoard[6][0], -90, 90);
            drawPoint(g2, gBoard[6][2], 0, 360);
            drawPoint(g2, gBoard[6][4], 0, 360);
            drawPoint(g2, gBoard[6][6], 0, 360);
            drawPoint(g2, gBoard[6][8], 90, 270);
            drawPoint(g2, gBoard[7][1], 0, 360);
            drawPoint(g2, gBoard[7][7], 0, 360);
        }

        private void drawPoint(Graphics2D g2, JPoint point, int startAngle, int endAngle) {
            int n = 0;
            int m = 0;
            for (int x = startAngle / 90; x < endAngle / 90; x++) {
                g2.drawLine(point.getX() + (int) (Math.cos(Math.toRadians(45 + 90 * x)) * squareWidth / 10) + n, point.getY() + (int) (Math.sin(Math.toRadians(45 + 90 * x)) * squareWidth / 10), point.getX() + (int) (Math.cos(Math.toRadians(45 + 90 * x)) * squareWidth / 10), point.getY() + (int) (Math.sin(Math.toRadians(45 + 90 * x)) * squareWidth / 5));
                g2.drawLine(point.getX() + (int) (Math.cos(Math.toRadians(45 + 90 * x)) * squareWidth / 10) + n, point.getY() + (int) (Math.sin(Math.toRadians(45 + 90 * x)) * squareWidth / 10) + m, point.getX() + (int) (Math.cos(Math.toRadians(45 + 90 * x)) * squareWidth / 5) + n, point.getY() + (int) (Math.sin(Math.toRadians(45 + 90 * x)) * squareWidth / 10) + m);
            }
        }
    }

    public class PieceLabel extends JLabel {
        private int x, y;
        private JPoint point;

        private PieceType pieceType;

        private boolean selected = false;

        public PieceLabel() {
            super();
        }

        public PieceLabel(int x, int y, JPoint point) {
            super();
            this.x = x;
            this.y = y;
            this.point = point;
            setHorizontalAlignment(JLabel.CENTER);
            setVerticalAlignment(JLabel.CENTER);
        }

        public void setPieceType(PieceType pieceType) {
            this.pieceType = pieceType;
        }

        public void setSelected(boolean selected) {
            this.selected = selected;
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);

            Graphics2D g2 = (Graphics2D) g;
            createEnglishPieces(g2);
        }

        void createEnglishPieces(Graphics2D g2) {
            setIcon(null);
            g2.setFont(new Font("Sans_Serif", Font.PLAIN, 12));
            FontMetrics metrics = g2.getFontMetrics();
            int xCoord, yCoord;
            if (null != pieceType && !PieceType.OTHER.equals(pieceType)) {
                g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);    // 消除画图锯齿
                g2.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_DEFAULT);        // 追求速度或质量
                g2.setColor(Color.white);
                g2.fillOval(3, 3, getWidth() - 6, getHeight() - 6);

                g2.setColor(Color.gray);
                g2.drawOval(2, 2, getWidth() - 4, getHeight() - 4);
                if (Alliance.BLACK != pieceType.getAlliance()) {
                    g2.setColor(Color.RED);
                } else {
                    g2.setColor(Color.BLACK);
                }

                xCoord = (getWidth()) / 2 - metrics.stringWidth(pieceType.getChinese().toString()) / 2;
                yCoord = (getHeight()) / 2 - metrics.getHeight() / 2 + metrics.getAscent();
                g2.drawString(pieceType.getChinese().toString(), xCoord, yCoord);

                if (selected) {

                    g2.setColor(Color.red);
                    g2.setStroke(new BasicStroke(2f));
                    int x = 0;
                    int y = 0;
                    int x1 = x - 16;
                    int y1 = y - 16;
                    // 左上角
                    g2.drawLine(x, y, x, y + 8);
                    g2.drawLine(x, y, x + 8, y);

                    // 右上角
                    g2.drawLine(x + 23, y, x + 32, y);
                    g2.drawLine(x + 31, y, x + 31, y + 8);

                    // 左下角
                    g2.drawLine(x, y + 23, x, y + 32);
                    g2.drawLine(x, y + 31, x + 8, y + 31);
//                    gBoard
                    // 右下角
                    g2.drawLine(x + 31, y + 23, x + 31, y + 31);
                    g2.drawLine(x + 23, y + 31, x + 32, y + 31);
                }

            }
        }
    }

    public void isRedAi() {
        android[REDPLAYSIGN] = !android[REDPLAYSIGN];
        if (android[REDPLAYSIGN] && (REDPLAYSIGN == play || turn_num <= 0)) {
            if (turn_num <= 0) {
                play = REDPLAYSIGN;
                moveHistory.play = 1 - REDPLAYSIGN;
            }
            computeThinkStart();
        }
    }

    public void isBlackAi() {
        android[BLACKPLAYSIGN] = !android[BLACKPLAYSIGN];
        if (android[BLACKPLAYSIGN] && (BLACKPLAYSIGN == play || turn_num <= 0)) {
            if (turn_num <= 0) {
                play = BLACKPLAYSIGN;
                moveHistory.play = 1 - BLACKPLAYSIGN;
            }
            computeThinkStart();
        }
    }

    public void setRed(boolean red) {
        isRed = red;
    }

}